#include "../include/pnactionbase.h"

using namespace pnNetlib;

/***************************************************************************************************************************/
pnActionBase::pnActionBase():
m_bIsInit(false),
m_iMaxSession(0),
m_icurListen(0),
m_icurConnect(0)
{

}

/***************************************************************************************************************************/
pnActionBase::~pnActionBase()
{
	if(m_bIsInit == true)
	{
		m_vecSession.clear();
		m_bIsInit = false;
	}
}

/***************************************************************************************************************************/
void
pnActionBase::inc_usage_count(eUsageType type)
{
    if(type == Usage_Listen)
        inter_lock::add(&m_icurListen, 1);

    if(type == Usage_Connect)
        inter_lock::add(&m_icurConnect, 1);
}

/***************************************************************************************************************************/
void
pnActionBase::dec_usage_count(eUsageType type)
{
    if(type == Usage_Listen)
        inter_lock::sub(&m_icurListen, 1);

    if(type == Usage_Connect)
        inter_lock::sub(&m_icurConnect, 1);
}

/***************************************************************************************************************************/
void
pnActionBase::recycle(int session_index, eUsageType type)
{
	boost::lock_guard<boost::mutex>    lock(m_mutex);

	m_stackValidIndex.push(session_index);
    dec_usage_count(type);
}

/***************************************************************************************************************************/
pnSession::SessionPtr
pnActionBase::get_valid_session()
{
	boost::lock_guard<boost::mutex>    lock(m_mutex);

	if(m_stackValidIndex.size() > 0)
	{
        int valid_index = m_stackValidIndex.top();
		m_stackValidIndex.pop();

		pnSession::SessionPtr validSession =  m_vecSession[valid_index];

		return validSession;
	}

	return pnSession::SessionPtr();
}

/***************************************************************************************************************************/
bool
pnActionBase::send_msg(int session_index, stPnMsgHeader* pHeader, void* pMsg)
{
	if((unsigned int)session_index <= m_vecSession.size())
	{
		pnSession::SessionPtr session = m_vecSession[session_index];
		if(session != 0)
		{
			if(session->is_open() == true)
			{
				return m_vecSession[session_index]->push_msg(pHeader, pMsg);
			}
		}
	}

	return false;
}

/***************************************************************************************************************************/
int
pnActionBase::send_msg_to_all(stPnMsgHeader* pHeader, void* pMsg, eUsageType type)
{
	int success_count = 0;
	for(int i = 0; i < m_iMaxSession; ++i)
	{
		if(get_type(i) == type && send_msg(i, pHeader, pMsg) == true)
			success_count++;
	}

	return success_count;
}

/***************************************************************************************************************************/
void
pnActionBase::vanish(int session_id)
{
	if((unsigned int)session_id <= m_vecSession.size())
	{
		pnSession::SessionPtr session = m_vecSession[session_id];
		if(session != 0)
		{
			if(session->is_open() == true)
				m_vecSession[session_id]->close();
		}
	}
}

/***************************************************************************************************************************/
void
pnActionBase::vanish()
{
	for(int i = 0; i < m_iMaxSession; ++i)
	{
		vanish(i);
	}
}

/***************************************************************************************************************************/
bool
pnActionBase::prepare(boost::asio::io_service &ioService, int max_session, long buffer_length)
{
	if(m_bIsInit == false)
	{
		if(buffer_length > pnNetlib::header_size)
		{
			for(int i = 0; i < max_session; ++i)
		    {
				pnSession::SessionPtr new_session(new pnSession(i, ioService, buffer_length));
			    m_vecSession.push_back(new_session);
			    m_stackValidIndex.push(i);
			}

			m_iMaxSession = max_session;
		    m_bIsInit = true;
			return m_bIsInit;
		}
	}

	return false;
}